"""
工单管理
"""
import logging
from datetime import datetime, timedelta

from django.db import transaction

from biz.core.thanos.models import WorkOrder, Reassign
from biz.exceptions import ERROR_DATA_NOT_EXISTS, ERROR_TIME_LIMIT
from biz.const import WorkOrderStatus, ProblemType, PayType, AppealType, CheckStatus, Role, UserStatus
from gis.common.django_ext.models import paginate
from gis.common.exceptions import BizException
from gis.admin.services import admin_service

_LOGGER = logging.getLogger(__name__)


def list_work_order(page_no, page_size, pro_id=None, player_id=None, data_id=None, type_id=None, status=None,
                    level=None, is_solved=None, handler_id=None, created_at_start=None, created_at_end=None,
                    amount_start=None, amount_end=None, pay_id=None, pay_type=None, appeal_type=None, pay_name=None,
                    pay_at_start=None, pay_at_end=None, order_by_urgent=False):
    assert page_no > 0
    assert page_size > 0
    query = WorkOrder.objects.all()
    if pro_id:
        query = query.filter(pro_id=pro_id)
    if data_id:
        query = query.filter(pk=data_id)
    if player_id:
        query = query.filter(player_id=player_id)
    if type_id:
        query = query.filter(type_id=type_id)
    if status is not None:
        query = query.filter(status=status)
    if level is not None:
        query = query.filter(level=level)
    if is_solved is not None:
        query = query.filter(is_solved=is_solved)
    if handler_id:
        query = query.filter(handler_id=handler_id)
    if pay_id:
        query = query.filter(pay_id=pay_id)
    if pay_type:
        query = query.filter(pay_type=pay_type)
    if appeal_type:
        query = query.filter(appeal_type=appeal_type)
    if pay_name:
        query = query.filter(pay_name=pay_name)
    if amount_start is not None:
        query = query.filter(amount__gte=amount_start)
    if amount_end is not None:
        query = query.filter(amount__lte=amount_end)
    if created_at_start:
        query = query.filter(created_at__gte=created_at_start)
    if created_at_end:
        query = query.filter(created_at__lte=created_at_end)
    if pay_at_start:
        query = query.filter(pay_at__gte=pay_at_start)
    if pay_at_end:
        query = query.filter(pay_at__lte=pay_at_end)
    query = query.order_by('-urgent_count', '-created_at') if order_by_urgent else query.order_by('-created_at')

    return query.count(), [e.to_dict() for e in paginate(query, page_no, page_size)]


def add_work_order(pro_id, player_id, type_id, level, chn, game_version, ua, platform, game=None, question_type=None,
                   appear_at=None, images=None, withdraw_id=None, withdraw_at=None, amount=None, company=None,
                   pay_id=None, pay_type=None, pay_name=None, pay_at=None, desc=None, cooperation=None):
    # 5分钟之内禁止再次提交订单
    recent_data = _get_recent_data(player_id)
    if recent_data and recent_data.created_at >= datetime.now() - timedelta(minutes=5):
        raise BizException(ERROR_TIME_LIMIT)

    with transaction.atomic():
        work_order = WorkOrder.objects.create(pro_id=pro_id, player_id=player_id, type_id=type_id, level=level, chn=chn,
                                              game_version=game_version, ua=ua, platform=platform, game=game,
                                              question_type=question_type, appear_at=appear_at, images=images,
                                              withdraw_id=withdraw_id, withdraw_at=withdraw_at, amount=amount,
                                              company=company, pay_id=pay_id, pay_type=pay_type, pay_name=pay_name,
                                              pay_at=pay_at, desc=desc, cooperation=cooperation)
        if type_id == ProblemType.RECHARGE:
            assert pay_type
            assert pay_id
            assert amount > 0
            assert pay_name
            assert pay_at
            if pay_type in [PayType.UNION_TRANSFER, PayType.OFFICE_AGENCY_CHARGE]:
                work_order.appeal_type = AppealType.UNIONAGENCY
            elif pay_type == PayType.MF_PAY:
                work_order.appeal_type = AppealType.MIAOPAY
            else:
                work_order.appeal_type = AppealType.JUSTPAY
        else:
            """
            客服分配逻辑
            """
            handler_id = assign_customer(pro_id)
            if handler_id:
                work_order.handler_id = handler_id
        work_order.save()


def get_work_order(data_id):
    data = _get_data(data_id)
    return data.to_dict()


def update_work_order(data_id, response=None, status=None, is_solved=None, remark=None, comment=None, handler_id=None):
    data = _get_data(data_id)
    if not data.handler_id:
        data.handler_id = handler_id
    if response:
        data.response = response
    if status is not None:
        data.status = status
        if status == WorkOrderStatus.FINISHED:
            data.finish_at = datetime.now()
            # 处理时长 = 处理时间 - 创建时间      如果转接 处理时间 - 转接时间
            data.process_time = (data.finish_at - data.reassign_at).seconds if data.reassign_at else (
                        data.finish_at - data.created_at).seconds
            data.checked = CheckStatus.WAIT  # 已处理的订单，将查看状态设置为0
            data.urgent_count = 0  # 已处理的订单，将加急次数设置为0
    if is_solved is not None:
        data.is_solved = is_solved
    if remark:
        data.remark = remark
    if comment is not None:
        data.comment = comment
    data.save()
    return data.to_dict()


def urgent_work_order(data_id):
    data = _get_data(data_id)
    data.urgent_count += 1
    data.urgent_at = datetime.now()
    data.save()
    return data.to_dict()


def reassign_work_order(data_id, user_id, to_user_id):
    with transaction.atomic():
        data = _get_data(data_id)
        from_user_id = data.handler_id
        data.handler_id = to_user_id
        data.reassign_at = datetime.now()
        data.save()

        stay_time = (data.reassign_at - data.created_at).seconds
        reassign = Reassign.objects.create(order_id=data_id, player_id=data.player_id, from_user_id=from_user_id,
                                           to_user_id=to_user_id, operator_id=user_id, stay_time=stay_time,
                                           pro_id=data.pro_id)
        return reassign.to_dict()


def _get_data(data_id):
    assert data_id > 0
    data = WorkOrder.objects.filter(pk=data_id).first()
    if not data:
        raise BizException(ERROR_DATA_NOT_EXISTS)
    return data


def _get_recent_data(player_id):
    assert player_id
    data = WorkOrder.objects.filter(player_id=player_id).order_by('-created_at').first()
    return data


def list_reassign(pro_id, page_no, page_size, order_id=None, player_id=None, from_user_id=None, to_user_id=None,
                  operator_id=None, created_at_start=None, created_at_end=None):
    assert page_no > 0
    assert page_size > 0
    query = Reassign.objects.filter(pro_id=pro_id).all()
    if order_id:
        query = query.filter(order_id=order_id)
    if player_id:
        query = query.filter(player_id=player_id)
    if from_user_id:
        query = query.filter(from_user_id=from_user_id)
    if to_user_id:
        query = query.filter(to_user_id=to_user_id)
    if operator_id:
        query = query.filter(operator_id=operator_id)
    if created_at_start:
        query = query.filter(created_at__gte=created_at_start)
    if created_at_end:
        query = query.filter(created_at__lte=created_at_end)
    return query.count(), [e.to_dict() for e in paginate(query, page_no, page_size)]


def get_rpc_work_order(data_id):
    data = _get_data(data_id)
    if data.status == WorkOrderStatus.FINISHED:
        data.checked = CheckStatus.CHECKED
        data.save()
    return data.to_dict()


def get_unchecked_count(player_id):
    count = WorkOrder.objects.filter(player_id=player_id).filter(status=WorkOrderStatus.FINISHED).filter(
        checked=CheckStatus.WAIT).count()
    return count


def assign_customer(pro_id):
    # 获取未处理订单最少的在线客服，相同的话，随机取一个
    page_no = 1
    page_size = 10000
    total, users = admin_service.list_users(pro_id, page_no, page_size, status=UserStatus.WORKING, role_id=Role.KEFU)
    uids = [e['id'] for e in users]
    if not total:
        return None  # 当前没有在线客服
    id_count = {}
    for uid in uids:
        count = WorkOrder.objects.filter(handler_id=uid).filter(status=WorkOrderStatus.WAITING).count()
        id_count.update({uid: count})
    return min(id_count, key=id_count.get)


def get_wait_order_count(user_id):
    count = WorkOrder.objects.filter(handler_id=user_id).filter(status=WorkOrderStatus.WAITING).count()
    return count
